﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Collections;
using System.Windows.Forms;

namespace Srv3CodeTool
{
        
    public enum MSGBOX_TYPE
    {
        MSGBOX_TYPE_INFO,
        MSGBOX_TYPE_NOTICE,
        MSGBOX_TYPE_WARNING,
        MSGBOX_TYPE_ERROR,
        MSGBOX_TYPE_ASK,
    }

    public enum IGNORE_TYPE
    {
        IGNORE_NONE,
        IGNORE_BRACKETS,
        IGNORE_AGLIN,
        IGNORE_BRANDAGLIN,
    }

    class Functions
    {
        private Config config = new Config();
        /// <summary>
        /// Common Function
        /// </summary>
        public Functions()
        {
            config.LoadFromXmlFile();
        }

        public static DialogResult ShowMsgBox(string strExpMsg, MSGBOX_TYPE eType)
        {
            string strMsgHead = "InforMation";
            MessageBoxIcon eIconType = MessageBoxIcon.Information;
            MessageBoxButtons eBtn = MessageBoxButtons.OK;
            switch (eType)
            {
                case MSGBOX_TYPE.MSGBOX_TYPE_INFO:
                    {
                        strMsgHead = "InforMation";
                        eIconType = MessageBoxIcon.Information;
                    }
                    break;
                case MSGBOX_TYPE.MSGBOX_TYPE_NOTICE:
                    {
                        strMsgHead = "Notice";
                        eIconType = MessageBoxIcon.Information;
                    }
                    break;
                case MSGBOX_TYPE.MSGBOX_TYPE_WARNING:
                    {
                        strMsgHead = "Warning";
                        eIconType = MessageBoxIcon.Warning;
                    }
                    break;
                case MSGBOX_TYPE.MSGBOX_TYPE_ERROR:
                    {
                        strMsgHead = "Error";
                        eIconType = MessageBoxIcon.Error;
                    }
                    break;
                case MSGBOX_TYPE.MSGBOX_TYPE_ASK:
                    {
                        strMsgHead = "Ask";
                        eIconType = MessageBoxIcon.Question;
                        eBtn = MessageBoxButtons.YesNo;
                    }
                    break;
            }
            return MessageBox.Show(strExpMsg, strMsgHead, eBtn, eIconType);
        }

        public string GetModulePath()
        {
            return config.ModePath;
        }

        public string GetModuleResPath()
        {
            return config.ModuleResPath;
        }

        public string GetTemplatePath()
        {
            return config.ModePath;
        }

        /// <summary>
        /// 创建虚拟目录
        /// </summary>
        /// <param name="sourceDirName">源文件目录名</param>
        /// <param name="destDirName">目标文件目录名</param>
        /// <param name="copySubDirs">是否拷贝子目录</param>
        private void DirectoryCopy(string sourceDirName, string destDirName, bool copySubDirs)
        {
            DirectoryInfo dir = new DirectoryInfo(sourceDirName);
            DirectoryInfo[] dirs = dir.GetDirectories();

            // If the source directory does not exist, throw an exception.
            if (!dir.Exists)
            {
                throw new DirectoryNotFoundException(
                    "Source directory does not exist or could not be found: "
                    + sourceDirName);
            }

            // If the destination directory does not exist, create it.
            if (!Directory.Exists(destDirName))
            {
                Directory.CreateDirectory(destDirName);
            }

            // Get the file contents of the directory to copy.
            FileInfo[] files = dir.GetFiles();

            foreach (FileInfo file in files)
            {
                // Create the path to the new copy of the file.
                string temppath = Path.Combine(destDirName, file.Name);

                // Copy the file.
                file.CopyTo(temppath, false);
            }

            // If copySubDirs is true, copy the subdirectories.
            if (copySubDirs)
            {
                foreach (DirectoryInfo subdir in dirs)
                {
                    // Create the subdirectory.
                    string temppath = Path.Combine(destDirName, subdir.Name);

                    // Copy the subdirectories.
                    DirectoryCopy(subdir.FullName, temppath, copySubDirs);
                }
            }
        }


        private void FileReplace(string szDirPath, string szTemplate, string szModuleName, bool bReplaceSub)
        {

        }
        /// <summary>
        /// 替换目录和文件
        /// </summary>
        /// <param name="szDirPath">文件目录名</param>
        /// <param name="szTemplate">文件中的模板名</param>
        /// <param name="szModuleName">模块名</param>
        /// <param name="bReplaceSub">是否替换子目录</param>
        private void DirectoryReplace(string szDirPath, string szTemplate, string szModuleName, bool bReplaceSub)
        {
            if (Directory.Exists(szDirPath))
            {
                string[] szFileArr = Directory.GetFiles(szDirPath);
                foreach (string szFile in szFileArr)
                {
                    string szNewFileName = szFile.Replace(szTemplate, szModuleName);
                    File.Move(szFile, szNewFileName);
                    string szFileContext = File.ReadAllText(szNewFileName, Encoding.GetEncoding("gb2312"));
                    szFileContext = szFileContext.Replace(szTemplate, szModuleName);
                    szFileContext = szFileContext.Replace(szTemplate.ToUpper(), szModuleName.ToUpper());
                    szFileContext = szFileContext.Replace(szTemplate.ToLower(), szModuleName.ToLower());
                    File.WriteAllText(szNewFileName, szFileContext, Encoding.GetEncoding("gb2312"));
                }

                if (bReplaceSub)
                {
                    string[] szSubDir = Directory.GetDirectories(szDirPath);
                    foreach (string szDir in szSubDir)
                    {
                        this.DirectoryReplace(szDir, szTemplate, szModuleName, bReplaceSub);
                    }
                }
            }
            else if (File.Exists(szDirPath))
            {
                    string szFile = szDirPath;
                    string szNewFileName = szFile.Replace(szTemplate, szModuleName);
                    File.Move(szFile, szNewFileName);
                    string szFileContext = File.ReadAllText(szNewFileName, Encoding.GetEncoding("gb2312"));
                    szFileContext = szFileContext.Replace(szTemplate, szModuleName);
                    szFileContext = szFileContext.Replace(szTemplate.ToUpper(), szModuleName.ToUpper());
                    szFileContext = szFileContext.Replace(szTemplate.ToLower(), szModuleName.ToLower());
                    File.WriteAllText(szNewFileName, szFileContext, Encoding.GetEncoding("gb2312"));
            }
        }

        private void WriteFileBetween(string szFilePath, string szFunction, string[] szBetweenCodeArr, string[] szToCodeArr)
        {
            string szFileContext = File.ReadAllText(szFilePath, Encoding.GetEncoding("gb2312"));
            int nIndexProviderClass = szFileContext.IndexOf("Provider"); //???
            if (nIndexProviderClass < 0)
                nIndexProviderClass = 0;

            int nToCodeIndex= Int32.MaxValue;
            int nToCodeLen  = 0;
            string szProviderClass = szFileContext.Substring(nIndexProviderClass);
            foreach(string szCode in szToCodeArr)
            {// find the min index of the Code Which is Both in the CodeArr And the Context
                if (szCode == null || szCode == "")
                    continue;
                int nTmpIndex = szProviderClass.IndexOf(szCode);
                if (nTmpIndex >= 0 && nTmpIndex < nToCodeIndex)
                {
                    nToCodeIndex = nTmpIndex;
                    nToCodeLen = szCode.Length;
                }
            }

            string szEndFunc = szProviderClass.Substring(0, nToCodeIndex);

            int nBetweenCodeIndex = -1;
            int nBetweenCodeLen = 0;
            foreach (string szCode in szBetweenCodeArr)
            {// find the max index of the Code Which is Both in the CodeArr And the Context
                if (szCode == null || szCode == "")
                    continue;
                int nTmpIndex = szProviderClass.LastIndexOf(szCode);
                if (nTmpIndex >= 0 && nTmpIndex > nBetweenCodeIndex)
                {
                    nBetweenCodeIndex = nTmpIndex;
                    nBetweenCodeLen = szCode.Length;
                }
            }
            if (nBetweenCodeIndex == -1)
                return;

            // combine the function to this file context
            string szFileB = szFileContext.Substring(0, nBetweenCodeIndex + nIndexProviderClass +nBetweenCodeLen );
            string szFileE = szFileContext.Substring(nBetweenCodeIndex + nIndexProviderClass + nBetweenCodeLen);
            string szContextWrite =  szFileB + szFunction + szFileE;

            // write this file
            FileStream fsfile = new FileStream(szFilePath, FileMode.Create, FileAccess.Write);
            StreamWriter swfile = new StreamWriter(fsfile, Encoding.GetEncoding("gb2312"));
            swfile.Write(szContextWrite);
            swfile.Flush();
            swfile.Close();

        }

        private bool IsAllkeyInString(string strSrc, ArrayList listKey)
        {
            if (!IsValidStr(strSrc))
                return false;
            object[] objKeyArr = listKey.ToArray();
            foreach (object objKey in objKeyArr)
            {
                string strKey = objKey.ToString();
                if (IsValidStr(strKey) && strSrc.IndexOf(strKey) < 0)
                    return false;
            }
            return true;
        }

        private bool IsValidStr(string str)
        {
            return (str != null && str != "");
        }

        public static Encoding GetEncodingType(string FILE_NAME)
        {
            FileStream fs = new FileStream(FILE_NAME, FileMode.Open, FileAccess.Read);
            System.Text.Encoding r = GetType(fs);
            fs.Close();
            return r;
        }

        public static Encoding GetType(FileStream fs)
        {
            byte[] Unicode = new byte[] { 0xFF, 0xFE };
            byte[] UnicodeBIG = new byte[] { 0xFE, 0xFF };
            byte[] UTF8 = new byte[] { 0xEF, 0xBB, 0xBF };

            BinaryReader r = new BinaryReader(fs, System.Text.Encoding.Default);
            byte[] ss = r.ReadBytes(3);
            r.Close();
            //编码类型 Coding=编码类型.ASCII;
            if (ss[0] >= 0xEF)
            {
                if (ss[0] == 0xEF && ss[1] == 0xBB && ss[2] == 0xBF)
                {
                    return System.Text.Encoding.UTF8;
                }
                else if (ss[0] == 0xFE && ss[1] == 0xFF)
                {
                    return System.Text.Encoding.BigEndianUnicode;
                }
                else if (ss[0] == 0xFF && ss[1] == 0xFE)
                {
                    return System.Text.Encoding.Unicode;
                }
                else
                {
                    return System.Text.Encoding.Default;
                }
            }
            else
            {
                return System.Text.Encoding.Default;
            }
        }

        /// <summary>
        /// 根据strStd对齐strSrc
        /// </summary>
        /// <returns></returns>
        private string AlignStr(string strSrc, string strStd)
        {
            string strVirtualAlign = "";
            string strTypeAlign = "";
            string strFuncBeginAlign = "";
            string strStateOrVirEnd = "";
            string strTemp = strStd;
            if (strStd.IndexOf("virtual") >= 0)
            {
                strVirtualAlign = strStd.Substring(0, strStd.IndexOf("virtual"));
                strTemp = strStd.Substring(strStd.IndexOf("virtual") + 7);
            }
            if (strTemp.IndexOf("bool") >= 0)
            {
                strTypeAlign = strTemp.Substring(0, strTemp.IndexOf("bool"));
                strTemp = strTemp.Substring(strTemp.IndexOf("bool") + 4);
            }
            else if (strTemp.IndexOf("void") >= 0)
            {
                strTypeAlign = strTemp.Substring(0, strTemp.IndexOf("void"));
                strTemp = strTemp.Substring(strTemp.IndexOf("void") + 4);
            }
            else if (strTemp.IndexOf("int") >= 0)
            {
                strTypeAlign = strTemp.Substring(0, strTemp.IndexOf("int"));
                strTemp = strTemp.Substring(strTemp.IndexOf("int") + 3);
            }

            if (strTemp.IndexOf("(") >= 0)
            {
                string strFunStart = strTemp.Substring(0, strTemp.IndexOf("("));
                int nIndexSpace = strFunStart.LastIndexOf(" ");
//                 int nIndexStart = strFunStart.LastIndexOf("*");
                int nIndext = strFunStart.LastIndexOf("\t");
                int nFunAlign = Math.Max(nIndexSpace, nIndext);
                strFuncBeginAlign = strTemp.Substring(0, nFunAlign+1);
                strTemp = strTemp.Substring(nFunAlign + 1);
            }
            else
                return strSrc;

            strTemp = strTemp.Substring(strTemp.IndexOf(")") + 1);

            if (strTemp.IndexOf("PURE_VIRTUAL") >= 0)
            {
                strStateOrVirEnd = strTemp.Substring(0, strTemp.IndexOf("PURE_VIRTUAL"));
            }
            else if (strTemp.IndexOf("{") >= 0)
            {
                strStateOrVirEnd = strTemp.Substring(0, strTemp.IndexOf("{"));
            }
            else if (strTemp.IndexOf(";") >= 0)
            {
                strStateOrVirEnd = strTemp.Substring(0, strTemp.IndexOf(";"));
            }
           
            string strFunction = "";
            string strResult = "";
            if (/*strSrc.IndexOf("virtual") >= 0 && */strStd.IndexOf("virtual") >= 0)
            {
                strResult = strResult + strVirtualAlign + "virtual";
            }

            if (strSrc.IndexOf("bool") >= 0)
            {
                strResult = strResult + strTypeAlign + "bool";
                strTemp = strSrc.Substring(strSrc.IndexOf("bool") + 4);
            }
            else if (strSrc.IndexOf("void") >= 0)
            {
                strResult = strResult + strTypeAlign + "void";
                strTemp = strSrc.Substring(strSrc.IndexOf("void") + 4);
            }
            else if (strSrc.IndexOf("int") >= 0)
            {
                strResult = strResult + strTypeAlign + "int ";
                strTemp = strSrc.Substring(strSrc.IndexOf("int") + 4);
            }
            string strTrim = "\r\n\t ";
            strTemp = strTemp.Trim(strTrim.ToCharArray());
            strFunction = strTemp.Substring(0, strTemp.IndexOf(")") + 1);
            strResult = strResult + strFuncBeginAlign + strFunction;
            if (strSrc.IndexOf("PURE_VIRTUAL_0") >= 0)
            {
                strResult = strResult + strStateOrVirEnd + "PURE_VIRTUAL_0";
            }
            else if (strSrc.IndexOf("PURE_VIRTUAL") >= 0)
            {
                strResult = strResult + strStateOrVirEnd + "PURE_VIRTUAL";
            }
            else if (strSrc.IndexOf(";") >= 0)
            {
                strResult = strResult + strStateOrVirEnd + ";";
            }

            return strResult;
        }

        /// <summary>
        /// 根据一定的规则在头文件中插入内容
        /// </summary>
        /// <param name="strFilePath">要修改的完成的头文件路径</param>
        /// <param name="strFunction">要插入的函数</param>
        /// <param name="strClass">要插入的类名</param>
        /// <param name="listBetweenStr">在最后这个的符号后插入</param>
        /// <param name="listToStr">在最先的这个符号之前插入</param>
        private int InSertFunction2HeadFile(string strFilePath, string strFunction, string strClass, ArrayList listBetweenStr, ArrayList listToStr, IGNORE_TYPE eIgnore)
        {
            if (!IsValidStr(strFilePath) || !IsValidStr(strFunction))
            {
                return -1; // the str is invalid
            }

            // read the all file context
            Encoding encode = GetEncodingType(strFilePath);
            string strFileContext = File.ReadAllText(strFilePath, encode);

            int nIndexClass = strFileContext.IndexOf(/*"class " + */strClass);
            if (nIndexClass < 0)
            {
                return -1; // no class
            }

            // find the first index in the arraylist
            string strTmp = strFileContext.Substring(nIndexClass);
            int nToStrIndex = strTmp.Length;
            object[] objToArr = listToStr.ToArray();
            int startIndex = strTmp.IndexOf("{") + 1;
            string strSub = strTmp.Substring(startIndex);
            int nCount = 0;
            while (eIgnore >= IGNORE_TYPE.IGNORE_BRACKETS && strTmp.IndexOf("{", startIndex) >= 0)
            {
                if (nCount++ > 10000)
                {
                    Log.LogSave("Dead Loop !!Break Now.", LOGTYPE.LOGTYPE_WARNING);
                    break;
                }
                startIndex = strTmp.IndexOf("}", startIndex) + 1;
                strSub = strTmp.Substring(startIndex);
            }

            nCount = 0;
//             while (strTmp.IndexOf("#if", startIndex) >= 0)
//             {
//                 if (nCount++ > 10000)
//                 {
//                     Log.LogSave("Dead Loop !!Break Now.", LOGTYPE.LOGTYPE_WARNING);
//                     break;
//                 }
//                 startIndex = strTmp.IndexOf("#endif", startIndex) + 1;
//                 strSub = strTmp.Substring(startIndex);
//             }
            foreach (object obj in objToArr)
            {
                string strTo = obj.ToString();
                if (!IsValidStr(strTo))
                    continue;
                if (strTmp.IndexOf(strTo, startIndex) < 0)
                    continue;
                int nTmpIndex = strTmp.IndexOf(strTo, startIndex) + strTo.Length;
                if (nTmpIndex >= 0 && nTmpIndex < nToStrIndex)
                {
                    nToStrIndex = nTmpIndex ;
                }
            }

            strTmp = strTmp.Substring(0, nToStrIndex);
            if (!IsValidStr(strTmp))
            {
                return -1;// no the class end(no "};")
            }

            // find the last index in the arraylist
            int nBeStrIndex = 0;
            object[] objBeArr = listBetweenStr.ToArray();
            foreach (object obj in objBeArr)
            {
                string strBe = obj.ToString();
                if (!IsValidStr(strBe))
                    continue;
                if (strTmp.LastIndexOf(strBe) < 0)
                    continue;
                int nTmpIndex = strTmp.LastIndexOf(strBe) + strBe.Length;
                if (nTmpIndex >= 0 && nTmpIndex > nBeStrIndex)
                {
                    nBeStrIndex = nTmpIndex;
                }
            }
            if (nBeStrIndex == -1)
            {
                return -1; // can't find any string in listbetweenstr
            }

            // combine the function to this file context
            string strFileB = strFileContext.Substring(0, nBeStrIndex + nIndexClass);
            string strFileE = strFileContext.Substring(nBeStrIndex + nIndexClass);
            if (eIgnore >= IGNORE_TYPE.IGNORE_AGLIN)
            {
                string strTrim = "\r\n";
                string strTemp = strFileB.Trim(strTrim.ToCharArray());
                strTemp = strTemp.Substring(strTemp.LastIndexOf("\n") + 1);
                strFunction = AlignStr(strFunction, strTemp);
            }

            if (strFileContext.IndexOf(strFunction) >= 0)
            {
                string strFile = strFilePath.Substring(0, strFilePath.LastIndexOf("\\"));
                if (ShowMsgBox(strFile + "已经有该函数，确认添加", MSGBOX_TYPE.MSGBOX_TYPE_ASK) == DialogResult.No)
                {
                    return -2;
                }
            }
            string szContextWrite = strFileB + "\r\n" + strFunction + strFileE;

            // write this file
            FileStream fsfile = new FileStream(strFilePath, FileMode.Create, FileAccess.Write);
            StreamWriter swfile = new StreamWriter(fsfile, encode);
            swfile.Write(szContextWrite);
            swfile.Flush();
            swfile.Close();
            return 0;
        }

        private void InSertFunction2CppFile(string strFilePath, string strFunction, ArrayList listBetweenStr, ArrayList listToStr, IGNORE_TYPE eIgnore)
        {
            if (!IsValidStr(strFilePath) || !IsValidStr(strFunction))
            {
                return; // the str is invalid
            }

            // read the all file context
            Encoding encode = GetEncodingType(strFilePath);
            string strFileContext = File.ReadAllText(strFilePath, encode);
//             if (strFileContext.IndexOf(strFunction) >= 0)
//             {
//                 string strFile = strFilePath.Substring(0, strFilePath.LastIndexOf("\\"));
//                 if (ShowMsgBox(strFile + "已经有该内容，确认添加", MSGBOX_TYPE.MSGBOX_TYPE_ASK) == DialogResult.No)
//                 {
//                     return;
//                 }
//             }

            // find the first index in the arraylist

            string strTmp = strFileContext;
            int nToStrIndex = strTmp.Length;
            object[] objToArr = listToStr.ToArray();
            int startIndex = 0;
            string strSub = strTmp.Substring(startIndex);
            int nCount = 0;
            while (eIgnore >= IGNORE_TYPE.IGNORE_BRACKETS && strTmp.IndexOf("{", startIndex) >= 0)
            {
                if (nCount++ > 10000)
                {
                    Log.LogSave("Dead Loop !!Break Now.", LOGTYPE.LOGTYPE_WARNING);
                    break;
                }
                startIndex = strTmp.IndexOf("}", startIndex) + 1;
                strSub = strTmp.Substring(startIndex);
            }

            foreach (object obj in objToArr)
            {
                string strTo = obj.ToString();
                if (!IsValidStr(strTo))
                    continue;
                if (strTmp.IndexOf(strTo, startIndex) < 0)
                    continue;
                int nTmpIndex = strTmp.IndexOf(strTo, startIndex) + strTo.Length;
                if (nTmpIndex >= 0 && nTmpIndex < nToStrIndex)
                {
                    nToStrIndex = nTmpIndex;
                }
            }

            strTmp = strTmp.Substring(0, nToStrIndex);
            if (!IsValidStr(strTmp))
            {
                return; // no the class end(no "};")
            }

            // find the last index in the arraylist
            int nBeStrIndex = 0;
            object[] objBeArr = listBetweenStr.ToArray();
            foreach (object obj in objBeArr)
            {
                string strBe = obj.ToString();
                if (!IsValidStr(strBe))
                    continue;
                if (strTmp.LastIndexOf(strBe) < 0)
                    continue;
                int nTmpIndex = strTmp.LastIndexOf(strBe) + strBe.Length;
                if (nTmpIndex >= 0 && nTmpIndex > nBeStrIndex)
                {
                    nBeStrIndex = nTmpIndex;
                }
            }
            if (nBeStrIndex == -1)
            {
                return; // can't find any string in listbetweenstr
            }

            // combine the function to this file context
            string strFileB = strFileContext.Substring(0, nBeStrIndex);
            string strFileE = strFileContext.Substring(nBeStrIndex);
            string szContextWrite = strFileB + "\r\n" + strFunction + strFileE;

            // write this file
            FileStream fsfile = new FileStream(strFilePath, FileMode.Create, FileAccess.Write);
            StreamWriter swfile = new StreamWriter(fsfile, encode);
            swfile.Write(szContextWrite);
            swfile.Flush();
            swfile.Close();

        }

        private string CollectStrLineFromFile(string strFilePath, ArrayList listKey)
        {
            if (!IsValidStr(strFilePath) || listKey.Count == 0)
                return "";

            Encoding encode = GetEncodingType(strFilePath);
            string[] strLineArr = File.ReadAllLines(strFilePath, encode);
            foreach (string str in strLineArr)
            {
                string strTrim = "\t ";
                string strLine = str.Trim(strTrim.ToCharArray());
                if (IsAllkeyInString(str, listKey))
                {
                    return str;
                }
            }
            return "";
        }

        public object[] GetModuleArray()
        {
            string[] szModulePathArr = Directory.GetDirectories(config.ModulePath);

            ArrayList listModule = new ArrayList();
            foreach (string szPath in szModulePathArr)
            {
                int nIndex = szPath.LastIndexOf('\\');
                string szModule = szPath.Substring(nIndex + 1);
                if (szModule.IndexOf(".") >= 0)
                    continue;
                if (szModule.IndexOf("Adapter") >= 0 || szModule.IndexOf("Include") >= 0 || szModule.IndexOf("Action") >= 0)
                    continue;
                listModule.Add(szModule);
            }
            return listModule.ToArray();
        }

        public object[] GetMsgArray()
        {
            string[] szMsgFileArr = Directory.GetFiles(config.ModulePath + "\\Include\\Msg");

            ArrayList listMsg = new ArrayList();
            foreach (string szMsg in szMsgFileArr)
            {
                int nIndexStart = szMsg.LastIndexOf('\\');
                int nIndexEnd = szMsg.LastIndexOf('.');
                if (szMsg.IndexOf(".") < 0)
                    continue;
                if (nIndexStart < 0 || nIndexEnd < 0)
                    continue;
                listMsg.Add(szMsg.Substring(nIndexStart + 2, nIndexEnd - 1 - nIndexStart -1));
            }
            return listMsg.ToArray();
        }

        public bool AdapterInterfaceNew(string szModulePro, string szFuncPro, string szModuleCon, string szConFunc)
        {
            string szFileProPath = config.ModulePath + "\\" + szModulePro + "\\Src\\Provider.h";

            // 如果函数有重载，则不行，不够精准
            ArrayList listParam1 = new ArrayList();
            listParam1.Add(szFuncPro);
            string szWholeFuncPro = CollectStrLineFromFile(szFileProPath, listParam1);

            string strTrim = "\r\n";
            szWholeFuncPro = szWholeFuncPro.Trim(strTrim.ToCharArray());
            string szWholeFuncCon = szWholeFuncPro.Replace(szFuncPro, szConFunc);

            // write the Iprovider interface
            string szFileIProPath = config.ModulePath + "\\Include\\Provider\\I" + szModulePro + "Provider.h";
            ArrayList listBe = new ArrayList();
            listBe.Add("PURE_VIRTUAL_0");
            listBe.Add("PURE_VIRTUAL");
            listBe.Add("public:");
            ArrayList listTo = new ArrayList();
            listTo.Add("private");
            listTo.Add("protected");
            listTo.Add("}");
            if (szWholeFuncPro.IndexOf("void") >= 0)
                szWholeFuncPro = szWholeFuncPro.Replace(";", "PURE_VIRTUAL");
            else
                szWholeFuncPro = szWholeFuncPro.Replace(";", "PURE_VIRTUAL_0");
            if (szWholeFuncPro.IndexOf("virtual") < 0)
                szWholeFuncPro = "virtual " + szWholeFuncPro;
            string strClass = "IProvider";
            if (InSertFunction2HeadFile(szFileIProPath, szWholeFuncPro, strClass, listBe, listTo, IGNORE_TYPE.IGNORE_BRANDAGLIN) == -2)
            {
                return false;
            }

            // write the IConsumer interface
            string szWholeFuncConv = szWholeFuncPro.Replace(szFuncPro, szConFunc);
            string szFileIConPath = config.ModulePath + "\\Include\\Consumer\\I" + szModuleCon + "Consumer.h";
            strClass = "IConsumer";
            InSertFunction2HeadFile(szFileIConPath, szWholeFuncConv, strClass, listBe, listTo, IGNORE_TYPE.IGNORE_BRANDAGLIN);

            string szFileConPath = config.ModulePath + "\\Adapter\\Consumer\\" + szModuleCon + "Consumer.h";
            string szConCppPath = config.ModulePath + "\\Adapter\\Consumer\\" + szModuleCon + "Consumer.cpp";
            Encoding encode = GetEncodingType(szFileConPath);
            string strFileContext = File.ReadAllText(szFileConPath, encode);
            if (strFileContext.IndexOf(szModulePro.ToLower()) < 0)
            {// if no the tunmanagedptr add it 
                listBe.Clear(); listTo.Clear();
                listBe.Add("\"");
                listTo.Add("NAMESPACE_BEGIN");
                listTo.Add("namespace");
                string strHeadInclude = "#include \"Provider/I"+szModulePro+"Provider.h\" ";
                InSertFunction2CppFile(szFileConPath, strHeadInclude, listBe, listTo, IGNORE_TYPE.IGNORE_NONE);
                listBe.Clear(); listTo.Clear();
                listBe.Add(";");
                listBe.Add("private:");
                listBe.Add("Provider;");
                listTo.Add("}");
                listTo.Add("private:");
                string strtunmanagedptr = "\tTunmanagedPtr<" + szModulePro.ToLower() + "::IProvider>\tm_p" + szModulePro + "Provider;";
                InSertFunction2CppFile(szFileConPath, strtunmanagedptr, listBe, listTo, IGNORE_TYPE.IGNORE_BRANDAGLIN);

                listBe.Clear(); listTo.Clear();
                listBe.Add(");");
                listBe.Add(") ;");
                listBe.Add(")\t;");
                listTo.Add("return true;");
                listTo.Add("}");
                strClass = "::Init";
                string strInitProvider = "\r\n\tm_p" + szModulePro + "Provider = static_cast<" + szModulePro.ToLower() + "::IProvider*>(m_root.QueryInterface(MOD_"+szModulePro.ToUpper()+"));";
                strInitProvider += "\r\n\tCHECKM (m_p" + szModulePro + "Provider);";
                InSertFunction2HeadFile(szConCppPath, strInitProvider, strClass, listBe, listTo, IGNORE_TYPE.IGNORE_NONE);
            }
            listBe.Clear(); listTo.Clear();
            listBe.Add(";");
            listTo.Add("}");
            listTo.Add("private");
            listTo.Add("protected");
            listTo.Add("}");
            strClass = "C" + szModuleCon + "Consumer";
            InSertFunction2HeadFile(szFileConPath, szWholeFuncCon, strClass, listBe, listTo, IGNORE_TYPE.IGNORE_BRANDAGLIN);

            listParam1.Clear();
            listParam1.Add("template");
            listParam1.Add("<");
            listParam1.Add(">");
            string strTemplate = CollectStrLineFromFile(szFileConPath, listParam1);
            strTrim = "\r\n\t";
            strTemplate = strTemplate.Trim(strTrim.ToCharArray());
            string strCppFunc   = "";
            strCppFunc += "//////////////////////////////////////////////////////////////////////////\r\n";
            strCppFunc += strTemplate + "\r\n";

            string strTmp = szWholeFuncCon.Substring(0, szWholeFuncCon.IndexOf(szConFunc));
            strTrim = ";\r\n\t";
            string strFuncType = strTmp.Trim(strTrim.ToCharArray());

            int nIndexA = strTemplate.IndexOf("<");
            int nIndexB = strTemplate.IndexOf(">");
            strTmp = strTemplate.Substring(nIndexA, nIndexB - nIndexA + 1);
            strTmp = strTmp.Replace("class ", "");

            string strFun = szWholeFuncCon.Substring(szWholeFuncCon.IndexOf(szConFunc));
            strFun = strFun.Replace(";", "");

            strCppFunc += strFuncType + " C" + szModuleCon + "Consumer" + strTmp + "::" + strFun+"\r\n";
            strCppFunc = strCppFunc.Replace("virtual ", "");
            strCppFunc += "{\r\n";

            listParam1.Clear();
            strTmp = "TUnmanagedPtr<"+szModulePro.ToLower()+"::IProvider>";
            listParam1.Add(szModulePro.ToLower());
            string strProPt = "m_p" + szModulePro+"Provider";
//             string strProPt = CollectStrLineFromFile(szFileConPath, listParam1);
//             strProPt = strProPt.Replace(strTmp, "");
//             strProPt = strProPt.Trim(strTrim.ToCharArray());
            strCppFunc += "\tif (" + strProPt + " == NULL)\r\n";
            if (strFuncType.IndexOf("void") >= 0)
            {
                strCppFunc += "\t\treturn ;";
                strTmp = strFun.Replace("OBJID ", "");
                strTmp = strTmp.Replace("int ", "");
                strCppFunc += "\r\n\t"+strProPt+"->"+strTmp+";\r\n";
            }
            else
            {
                strCppFunc += "\t\treturn false;\r\n";
                strTmp = strFun.Replace("OBJID ", "");
                strTmp = strTmp.Replace("int ", "");
                strTmp = strTmp.Replace("const char* ", "");
                strCppFunc += "\treturn " + strProPt + "->" + strTmp + ";\r\n";
            }

            strCppFunc += "}";
            strCppFunc = "\r\n" + strCppFunc;
            listBe.Clear(); listTo.Clear();
            listBe.Add("}");
            listTo.Add("#endif");
            InSertFunction2CppFile(szConCppPath, strCppFunc, listBe, listTo, IGNORE_TYPE.IGNORE_NONE);
            return true;
            //File.AppendAllText(szConCppPath, "\r\n" + strCppFunc);
        }

        //////////////////////////////////////////////////////////////////////////
        // 新生成lua脚本
        public void AddLuaScript(bool IsLua, string szBlockNum,  char[] szLuaScript)
        {
            string szFilePath = "";
            if (IsLua)
            {
                szFilePath = config.ModuleResPath + "\\" + "cq_lua.sql"; 
            }
            else
            {
                szFilePath = config.ModuleResPath + "\\" + "cq_cfg_lua.sql"; 
            }

            FileStream fsMyfile = new FileStream(szFilePath, FileMode.Append, FileAccess.Write);
            // 创建一个数据流写入器，和打开的文件关联
            StreamWriter swMyfile = new StreamWriter(fsMyfile);

            // 以文本方式写一个文件
            swMyfile.WriteLine("###################################################");
            swMyfile.WriteLine("#Author:\t" + config.UserName);
            swMyfile.WriteLine("#编号范围:\t" + szBlockNum);
            swMyfile.WriteLine("INSERT INTO cq_lua (0, " + szBlockNum + ", '" + szLuaScript.ToString() + "');");
            swMyfile.WriteLine("###################################################");
            swMyfile.Flush();
        }

        public void AddLuaScriptByMode(bool IsLua, string szModuleName, string szBlockNum, string szLuaScript)
        {
            string szModeFile = config.ModePath + "\\NewLua\\NewLua.sql";
            // 解析lua模板
            string szNewLuaMode = File.ReadAllText(szModeFile, Encoding.GetEncoding("gb2312"));
            szNewLuaMode = szNewLuaMode.Replace("__UserName__", config.UserName);
            szNewLuaMode = szNewLuaMode.Replace("__ModuleName__", szModuleName);
            szNewLuaMode = szNewLuaMode.Replace("__BlockNum__", szBlockNum);

            string szLuaSql = "";
            string szDelemte = "\r\n";
            string[] szLuaLineArr = szLuaScript.Split(szDelemte.ToCharArray());
            bool bStart = true;
            foreach (string szLuaLine in szLuaLineArr)
            {
                if (bStart)
                {
                    bStart = false;
                    szLuaSql += "INSERT INTO cq_lua (0, " + szBlockNum + ", '" + szLuaLine + "');";
                }
                else
                {
                    szLuaSql += "\r\nINSERT INTO cq_lua (0, " + szBlockNum + ", '" + szLuaLine + "');";
                }
            }
            szNewLuaMode = szNewLuaMode.Replace("__LuaScript__", szLuaSql);

            // 解析后的结果加到lua sql中
            string szFilePath = "";
            if (IsLua)
                szFilePath = config.ModuleResPath + "\\" + "cq_lua.sql";
            else
                szFilePath = config.ModuleResPath + "\\" + "cq_cfg_lua.sql";

            File.AppendAllText(szFilePath, szNewLuaMode);
        }

        public bool CreateNewModuleByMode(string szModuleName, string[] szMsgArr)
        {
            // 1. 拷贝mode中的__Module__到Module目录
            string szSrc = config.ModePath + "\\NewModule\\__Module__";
            string szDst = config.ModePath + "\\NewModule\\" + szModuleName;
            string strNewModulePath = config.ModulePath + "\\" + szModuleName;
            if (Directory.Exists(szDst) || Directory.Exists(strNewModulePath))
            {
                ShowMsgBox("不能重复生成模块!", MSGBOX_TYPE.MSGBOX_TYPE_WARNING);
                return false;
            }
            DirectoryCopy(szSrc, szDst, true);

            // 2. 替换文件
            DirectoryReplace(szDst, "__Module__", szModuleName, true);

            // 3. copy iprovider.h && replace it
            szSrc = config.ModePath + "\\NewModule\\I__Module__Provider.h";
            szDst = config.ModulePath + "\\Include\\Provider\\I"+ szModuleName +"Provider.h";
            File.Copy(szSrc, szDst);
            DirectoryReplace(szDst, "__Module__", szModuleName, true);

            // 4. copy iconsumer.h && replace it
            szSrc = config.ModePath + "\\NewModule\\I__Module__Consumer.h";
            szDst = config.ModulePath + "\\Include\\Consumer\\I" + szModuleName + "Consumer.h";
            File.Copy(szSrc, szDst);
            DirectoryReplace(szDst, "__Module__", szModuleName, true);

            /*
            // 5. 写define modulename MOD_MODULENAME
            string strDefinePath = config.ModePath + "\\Include\\Define.h";
            ArrayList listParam1 = new ArrayList();
            ArrayList listParam2 = new ArrayList();
            listParam1.Add("\"");
            string strFunction = "#define MOD_"+szModuleName.ToUpper();
            InSertFunction2HeadFile(strDefinePath, strFunction, "#ifndef", listParam1, listParam2, IGNORE_TYPE.IGNORE_BRACKETS);

            // 6. 写adapterex.cpp
            listParam1.Clear();
            listParam2.Clear();
            string strAdapterCppPath = config.ModePath + "\\Adapter\\Src\\AdapterEx.cpp";
            if (!File.Exists(strAdapterCppPath))
            {
                ShowMsgBox(strAdapterCppPath + "不存在", MSGBOX_TYPE.MSGBOX_TYPE_ERROR);
            }
            string[] strLineArr = File.ReadAllLines(strAdapterCppPath);
            string strContext = "";
            File.WriteAllLines(strAdapterCppPath, strLineArr);
            foreach (string strLine in strLineArr)
            {
                if (strLine.IndexOf("else") >= 0 && strLine.IndexOf("if") < 0)
                {
                    string strNewElseif = "\telse if (::strcmp(pszModule, MOD_" + szModuleName.ToUpper() +") == 0)\r\n";
                    strNewElseif += "\t{\r\n";
                    strNewElseif += "\t\tCREATE_CONSUMER8(C"+szModuleName.ToUpper()+"Consumer, "+szModuleName.ToLower()+", CItemConsumer, CMapConsumer, CNetConsumer, CNpcConsumer, CUserConsumer, CSpiritConsumer, CMonsterConsumer, CRoleConsumer);\r\n";
                    strNewElseif += "\t\tREGISTER_MODULE8(BIND_ITEM_EX, BIND_MAP_EX, BIND_NPC_EX, BIND_USER_EX, BINGD_SPIRIT_EX, BIND_MONSTER_EX, BIND_ROLE_EX)\r\n";
                    strNewElseif += "\t}\r\n";
                    strContext   += strNewElseif; 
                }
                strContext += strLine + "\r\n";
            }
            File.WriteAllText(strAdapterCppPath, strContext);
            */
            // 7.整理Module.cpp处理监听消息等等

            szSrc = config.ModePath + "\\NewModule\\" + szModuleName;
            szDst = config.ModulePath + "\\" + szModuleName;
            Directory.Move(szSrc, szDst);
            return true;
        }
        private string DropOtherArea(string strSrc, string strStart, string strEnd)
        {
            string strBeCheck = strSrc;
            int nIndexStart = strBeCheck.IndexOf(strStart);
            if (nIndexStart >= 0)
            {
                strBeCheck = strBeCheck.Substring(0, nIndexStart+1) + DropOtherArea(strBeCheck.Substring(nIndexStart+1), strStart, strEnd);
            }
            int nIndexAreaEnd = strBeCheck.LastIndexOf(strEnd);
            int nIndexAreaBegin = strBeCheck.IndexOf(strStart);
            if (nIndexAreaBegin >= 0 && nIndexAreaEnd >= 0 && nIndexAreaEnd > nIndexAreaBegin)
            {
                string strOtherArea = strBeCheck.Substring(nIndexAreaBegin, nIndexAreaEnd - nIndexAreaBegin + 1);
                strBeCheck = strBeCheck.Replace(strOtherArea, "");
            }
            return strBeCheck;
        }
/*
        private string DropOtherArea(string strSrc, string strStart, string strEnd)
        {
            int nCount = 0;
            string strBeCheck = strSrc;
            while (strBeCheck.LastIndexOf(strEnd) >= 0)
            {
                if (nCount++ > 10000) break;

                int nIndexAreaEnd = strBeCheck.LastIndexOf(strEnd);
                if (nIndexAreaEnd < 0)
                {
                    break;
                }
                string strSub = strBeCheck.Substring(0, nIndexAreaEnd);
                int nIndexAreaBegin = strSub.IndexOf(strStart);
                if (nIndexAreaBegin < 0)
                {
                    break;
                }
                string strOtherArea = strBeCheck.Substring(nIndexAreaBegin, nIndexAreaEnd - nIndexAreaBegin +1);
                strBeCheck = strBeCheck.Replace(strOtherArea, "");
            }
            return strBeCheck;
        }
*/
        private bool IsStrCheckPtr(string strSrc, string strPtr)
        {
            string strBeCheck = DropOtherArea(strSrc, "{", "}");
            ArrayList listCheckIf = new ArrayList();
            listCheckIf.Add("IF_NOT");
            listCheckIf.Add("IF_OK");
            listCheckIf.Add("if");
            listCheckIf.Add("CHECKF");
            listCheckIf.Add("CHECK");
            
            object[] objCheckIfArr = listCheckIf.ToArray();
            foreach (object objCheckIf in objCheckIfArr)
            {
                string strCheckIf = objCheckIf.ToString();
                int nstartIndex = 0;
                int nCount = 0;
                while (IsValidStr(strCheckIf) && strBeCheck.IndexOf(strCheckIf, nstartIndex) >= 0)
                {
                    if (nCount++ > 10000) break;
                    int nIndexIf = strBeCheck.IndexOf(strCheckIf, nstartIndex);
                    int nIndexIfBegin = strBeCheck.IndexOf("(", nIndexIf);
                    string strTmp = strBeCheck.Substring(nIndexIfBegin + 1);
                    nstartIndex = nIndexIfBegin + 1;
                    strTmp = DropOtherArea(strTmp, "(", ")");
                    int nIndexIfEnd = strTmp.IndexOf(")");
                    if (nIndexIfEnd >= 0)
                    {
                        strTmp = strTmp.Substring(0, nIndexIfEnd);
                    }
                    if (strTmp.IndexOf(strPtr) >= 0)
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        private string CheckPtrFromFile(string strFilePath)
        {
            string strResult = "";
            string strContext = File.ReadAllText(strFilePath);
            int nIndexClassBegin = strFilePath.LastIndexOf("\\");
            int nIndexClassEnd = strFilePath.LastIndexOf(".cpp");
            if (nIndexClassBegin < 0 || nIndexClassEnd <0)
            {
                return strResult;
            }

            string strFileName = strFilePath.Substring(nIndexClassBegin + 1, nIndexClassEnd - nIndexClassBegin-1);
            string strClass = "C" + strFileName +"::";
            int nStartIndex = 0;
            int nCheckStrLen = strContext.Length;
            string strPtrChecked = "";
            ArrayList listPtr = new ArrayList();
            string strFuncChecked = "";

            for (int nPtrIndex = strContext.IndexOf("->", nStartIndex); nPtrIndex > 0; nStartIndex = nPtrIndex + 2, nPtrIndex = strContext.IndexOf("->", nStartIndex))
            {
                string strCheckEnd = strContext.Substring(0, nPtrIndex);

                if (strCheckEnd.LastIndexOf(strClass) < 0)
                {// not in the fucntion, not to check ptr
                    continue;
                }
                int nFuncBegin = strCheckEnd.LastIndexOf(strClass) + strClass.Length;
                int nFuncEnd   = strCheckEnd.IndexOf("(", nFuncBegin);
                string strFunc = strCheckEnd.Substring(nFuncBegin, nFuncEnd- nFuncBegin);
                if (strFunc != strFuncChecked)
                {
                    listPtr.Clear();
                }

                if (strCheckEnd.LastIndexOf("::") >= 0)
                {
                    int nIndexInstance = strCheckEnd.LastIndexOf("::") + 1;
                    if (nIndexInstance >= 0 && strCheckEnd.Substring(nIndexInstance).IndexOf("instance", StringComparison.CurrentCultureIgnoreCase) >= 0)
                    {
                        continue;
                    }
                }

                int nIndexPtrName = strCheckEnd.LastIndexOf(" ");
                nIndexPtrName = Math.Max(nIndexPtrName, strCheckEnd.LastIndexOf("\t"));
                nIndexPtrName = Math.Max(nIndexPtrName, strCheckEnd.LastIndexOf("\n"));
                nIndexPtrName = Math.Max(nIndexPtrName, strCheckEnd.LastIndexOf("("));
                nIndexPtrName = Math.Max(nIndexPtrName, strCheckEnd.LastIndexOf("{"));
                nIndexPtrName = Math.Max(nIndexPtrName, strCheckEnd.LastIndexOf("*"));
                nIndexPtrName = Math.Max(nIndexPtrName, strCheckEnd.LastIndexOf(","));
                nIndexPtrName = Math.Max(nIndexPtrName, strCheckEnd.LastIndexOf("!"));
                nIndexPtrName = Math.Max(nIndexPtrName, strCheckEnd.LastIndexOf("="));
                nIndexPtrName = Math.Max(nIndexPtrName, strCheckEnd.LastIndexOf("/"));
                nIndexPtrName = Math.Max(nIndexPtrName, strCheckEnd.LastIndexOf(")"));
                nIndexPtrName = Math.Max(nIndexPtrName, strCheckEnd.LastIndexOf(":"));
                // the name of ptr
                string strPtr = strCheckEnd.Substring(nIndexPtrName + 1);
                strPtr = strPtr.Replace(")","");
                if (strPtr == "this")
                {
                    continue;
                }
                if (listPtr.Contains(strPtr))
                {
                    continue;
                }
                string strNextLine = strCheckEnd.Substring(0, nIndexPtrName);
                int nIndexNextLine = strNextLine.LastIndexOf("\n");
                if (nIndexNextLine >= 0 && strNextLine.IndexOf("//", nIndexNextLine+ 1) >= 0)
                {
                    continue;
                }


                listPtr.Add(strPtr);
                strPtrChecked = strPtr;
                strFuncChecked = strFunc;
                string strCheck = strCheckEnd.Substring(nFuncBegin, nIndexPtrName - nFuncBegin);
                if (!IsStrCheckPtr(strCheck, strPtr))
                {
                    strResult += "指针:" + strPtr + "在文件" + strFileName + ".cpp函数" + strFunc + "中没有检查,请核对。。。\r\n";
                }
                else
                {
                    continue;
                }
                

//                 int nIndexAreaEnd = strCheckEnd.LastIndexOf("}");
//                 if (nIndexAreaEnd > 0 && nIndexAreaEnd < strCheckEnd.Length)
//                 {
//                     string strCheck = strContext.Substring(nIndexAreaEnd + 1, nPtrIndex);
//                     if (IsStrCheckPtr(strCheck, strPtr))
//                     {
//                         continue;
//                     }
//                     strCheckEnd = strCheckEnd.Substring(0, );
//                     strContext.Substring(0, nIndexAreaEnd).LastIndexOf("{");
//                 }
            }
            return strResult;
        }

        public string CheckPtrFromPath(string strPath, bool bCheckSub)
        {
            string strResult = "";
            string[] szFileArr = Directory.GetFiles(strPath);
            foreach (string strFile in szFileArr)
            {
                if (strFile.Substring(strFile.Length - 4) == ".cpp")
                {
                    strResult += CheckPtrFromFile(strFile);
                }
            }

            if (bCheckSub)
            {
                string[] strSubDir = Directory.GetDirectories(strPath);
                foreach (string strDir in strSubDir)
                {
                    CheckPtrFromPath(strDir, bCheckSub);
                }
            }
            return strResult;
        }
    }
}
